home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume13 / gmcalc / part05 < prev    next >
Encoding:
Text File  |  1990-06-05  |  57.2 KB  |  1,868 lines

  1. Newsgroups: comp.sources.misc
  2. From: daveg@csvax.caltech.edu (David Gillespie)
  3. Subject: v13i031: Emacs Calculator 1.01, part 05/19
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 13, Issue 31
  7. Submitted-by: daveg@csvax.caltech.edu (David Gillespie)
  8. Archive-name: gmcalc/part05
  9.  
  10. ---- Cut Here and unpack ----
  11. #!/bin/sh
  12. # this is part 5 of a multipart archive
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file calc-ext.el continued
  15. #
  16. CurArch=5
  17. if test ! -r s2_seq_.tmp
  18. then echo "Please unpack part 1 first!"
  19.      exit 1; fi
  20. ( read Scheck
  21.   if test "$Scheck" != $CurArch
  22.   then echo "Please unpack part $Scheck next!"
  23.        exit 1;
  24.   else exit 0; fi
  25. ) < s2_seq_.tmp || exit 1
  26. echo "x - Continuing file calc-ext.el"
  27. sed 's/^X//' << 'SHAR_EOF' >> calc-ext.el
  28. X     ( atan       . calcFunc-arctan )
  29. X     ( atan2       . calcFunc-arctan2 )
  30. X     ( atanh       . calcFunc-arctanh )
  31. X))
  32. X
  33. X(put 'c 'math-variable-table
  34. X  '( ( M_PI       . var-pi )
  35. X     ( M_E       . var-e )
  36. X))
  37. X
  38. X(put 'c 'math-vector-brackets "{}")
  39. X
  40. X(put 'c 'math-radix-formatter
  41. X     (function (lambda (r s)
  42. X         (if (= r 16) (format "0x%s" s)
  43. X           (if (= r 8) (format "0%s" s)
  44. X             (format "%d#%s" r s))))))
  45. X
  46. X
  47. X(defun calc-pascal-language (n)
  48. X  "Set Pascal-language entry and display notation."
  49. X  (interactive "P")
  50. X  (calc-wrapper
  51. X   (calc-set-language 'pascal n))
  52. X)
  53. X
  54. X(put 'pascal 'math-oper-table
  55. X  '( ( "not"   calcFunc-lnot -1 1000 )
  56. X     ( "*"     *         190 191 )
  57. X     ( "/"     /         190 191 )
  58. X     ( "and"   calcFunc-and  190 191 )
  59. X     ( "div"   calcFunc-idiv 190 191 )
  60. X     ( "mod"   %         190 191 )
  61. X     ( "u+"    ident         -1  185 )
  62. X     ( "u-"    neg         -1  185 )
  63. X     ( "+"     +         180 181 )
  64. X     ( "-"     -         180 181 )
  65. X     ( "or"    calcFunc-or   180 181 )
  66. X     ( "xor"   calcFunc-xor  180 181 )
  67. X     ( "shl"   calcFunc-lsh  180 181 )
  68. X     ( "shr"   calcFunc-rsh  180 181 )
  69. X     ( "in"    calcFunc-in   160 161 )
  70. X     ( "<"     calcFunc-lt   160 161 )
  71. X     ( ">"     calcFunc-gt   160 161 )
  72. X     ( "<="    calcFunc-leq  160 161 )
  73. X     ( ">="    calcFunc-geq  160 161 )
  74. X     ( "="     calcFunc-eq   160 161 )
  75. X     ( "<>"    calcFunc-neq  160 161 )
  76. X     ( ":="    calcFunc-assign 81 80 )
  77. X))
  78. X
  79. X(put 'pascal 'math-input-filter 'calc-input-case-filter)
  80. X(put 'pascal 'math-output-filter 'calc-output-case-filter)
  81. X
  82. X(defun calc-input-case-filter (str)
  83. X  (cond ((or (null calc-language-option) (= calc-language-option 0))
  84. X     str)
  85. X    (t
  86. X     (downcase str)))
  87. X)
  88. X
  89. X(defun calc-output-case-filter (str)
  90. X  (cond ((or (null calc-language-option) (= calc-language-option 0))
  91. X     str)
  92. X    ((> calc-language-option 0)
  93. X     (upcase str))
  94. X    (t
  95. X     (downcase str)))
  96. X)
  97. X
  98. X
  99. X(defun calc-fortran-language (n)
  100. X  "Set Fortran-language entry and display notation."
  101. X  (interactive "P")
  102. X  (calc-wrapper
  103. X   (calc-set-language 'fortran n))
  104. X)
  105. X
  106. X(put 'fortran 'math-oper-table
  107. X  '( ( "**"    ^             201 200 )
  108. X     ( "u+"    ident         -1  191 )
  109. X     ( "u-"    neg         -1  191 )
  110. X     ( "*"     *         190 191 )
  111. X     ( "/"     /         190 191 )
  112. X     ( "+"     +         180 181 )
  113. X     ( "-"     -         180 181 )
  114. X))
  115. X
  116. X(put 'fortran 'math-vector-brackets "//")
  117. X
  118. X(put 'fortran 'math-function-table
  119. X  '( ( acos       . calcFunc-arccos )
  120. X     ( acosh       . calcFunc-arccosh )
  121. X     ( aimag       . calcFunc-im )
  122. X     ( aint       . calcFunc-ftrunc )
  123. X     ( asin       . calcFunc-arcsin )
  124. X     ( asinh       . calcFunc-arcsinh )
  125. X     ( atan       . calcFunc-arctan )
  126. X     ( atan2       . calcFunc-arctan2 )
  127. X     ( atanh       . calcFunc-arctanh )
  128. X     ( conjg       . calcFunc-conj )
  129. X     ( log       . calcFunc-ln )
  130. X     ( nint       . calcFunc-round )
  131. X     ( real       . calcFunc-re )
  132. X))
  133. X
  134. X(put 'fortran 'math-input-filter 'calc-input-case-filter)
  135. X(put 'fortran 'math-output-filter 'calc-output-case-filter)
  136. X
  137. X
  138. X(defun calc-tex-language (n)
  139. X  "Set TeX entry and display notation."
  140. X  (interactive "P")
  141. X  (calc-wrapper
  142. X   (calc-set-language 'tex n))
  143. X)
  144. X
  145. X(put 'tex 'math-oper-table
  146. X  '( ( "u+"       ident           -1 1000 )
  147. X     ( "u-"       neg           -1 1000 )
  148. X     ( "u|"       calcFunc-abs       -1    0 )
  149. X     ( "|"        ident            0   -1 )
  150. X     ( "\\lfloor" calcFunc-floor   -1    0 )
  151. X     ( "\\rfloor" ident             0   -1 )
  152. X     ( "\\lceil"  calcFunc-ceil    -1    0 )
  153. X     ( "\\rceil"  ident             0   -1 )
  154. X     ( "\\pm"      sdev           300 300 )
  155. X     ( "!"        calcFunc-fact       210  -1 )
  156. X     ( "^"      ^           201 200 )
  157. X     ( "_"      calcFunc-subscr  201 200 )
  158. X     ( "\\times"  *           191 190 )
  159. X     ( "2x"      *           191 190 )
  160. X     ( "+"      +           180 181 )
  161. X     ( "-"      -           180 181 )
  162. X     ( "\\over"      /           170 171 )
  163. X     ( "/"      /           170 171 )
  164. X     ( "\\choose" calcFunc-choose  170 171 )
  165. X     ( "\\mod"      %           170 171 )
  166. X))
  167. X
  168. X(put 'tex 'math-function-table
  169. X  '( ( \\arccos       . calcFunc-arccos )
  170. X     ( \\arcsin       . calcFunc-arcsin )
  171. X     ( \\arctan       . calcFunc-arctan )
  172. X     ( \\arg       . calcFunc-arg )
  173. X     ( \\cos       . calcFunc-cos )
  174. X     ( \\cosh       . calcFunc-cosh )
  175. X     ( \\det       . calcFunc-det )
  176. X     ( \\exp       . calcFunc-exp )
  177. X     ( \\gcd       . calcFunc-gcd )
  178. X     ( \\ln       . calcFunc-ln )
  179. X     ( \\log       . calcFunc-log10 )
  180. X     ( \\max       . calcFunc-max )
  181. X     ( \\min       . calcFunc-min )
  182. X     ( \\tan       . calcFunc-tan )
  183. X     ( \\sin       . calcFunc-sin )
  184. X     ( \\sinh       . calcFunc-sinh )
  185. X     ( \\tanh       . calcFunc-tanh )
  186. X     ( \\phi       . calcFunc-totient )
  187. X     ( \\mu       . calcFunc-moebius )
  188. X))
  189. X
  190. X(put 'tex 'math-variable-table
  191. X  '( ( \\pi       . var-pi )
  192. X))
  193. X
  194. X(put 'tex 'math-complex-format 'i)
  195. X
  196. X
  197. X(defun calc-mathematica-language ()
  198. X  "Set Mathematica(tm) entry and display notation."
  199. X  (interactive)
  200. X  (calc-wrapper
  201. X   (calc-set-language 'math))
  202. X)
  203. X
  204. X(put 'math 'math-oper-table
  205. X  '( ( "!"     calcFunc-fact  210 -1 )
  206. X     ( "!!"    calcFunc-dfact 210 -1 )
  207. X     ( "^"     ^         201 200 )
  208. X     ( "u+"    ident         -1  197 )
  209. X     ( "u-"    neg         -1  197 )
  210. X     ( "/"     /         195 196 )
  211. X     ( "*"     *         190 191 )
  212. X     ( "2x"    *         190 191 )
  213. X     ( "+"     +         180 181 )
  214. X     ( "-"     -         180 181 )
  215. X     ( "<"     calcFunc-lt   160 161 )
  216. X     ( ">"     calcFunc-gt   160 161 )
  217. X     ( "<="    calcFunc-leq  160 161 )
  218. X     ( ">="    calcFunc-geq  160 161 )
  219. X     ( "=="    calcFunc-eq   150 151 )
  220. X     ( "!="    calcFunc-neq  150 151 )
  221. X     ( "&&"    calcFunc-land 110 111 )
  222. X     ( "||"    calcFunc-lor  100 101 )
  223. X))
  224. X
  225. X(put 'math 'math-function-table
  226. X  '( ( Abs       . calcFunc-abs )
  227. X     ( ArcCos       . calcFunc-arccos )
  228. X     ( ArcCosh       . calcFunc-arccosh )
  229. X     ( ArcSin       . calcFunc-arcsin )
  230. X     ( ArcSinh       . calcFunc-arcsinh )
  231. X     ( ArcTan       . calcFunc-arctan )
  232. X     ( ArcTanh       . calcFunc-arctanh )
  233. X     ( Arg       . calcFunc-arg )
  234. X     ( Binomial       . calcFunc-choose )
  235. X     ( Ceiling       . calcFunc-ceil )
  236. X     ( Conjugate   . calcFunc-conj )
  237. X     ( Cos       . calcFunc-cos )
  238. X     ( Cosh       . calcFunc-cosh )
  239. X     ( D       . calcFunc-deriv )
  240. X     ( Dt       . calcFunc-tderiv )
  241. X     ( Det       . calcFunc-det )
  242. X     ( Exp       . calcFunc-exp )
  243. X     ( EulerPhi       . calcFunc-totient )
  244. X     ( Floor       . calcFunc-floor )
  245. X     ( Gamma       . calcFunc-gamma )
  246. X     ( GCD       . calcFunc-gcd )
  247. X     ( If       . calcFunc-if )
  248. X     ( Im       . calcFunc-im )
  249. X     ( Inverse       . calcFunc-inv )
  250. X     ( Join       . calcFunc-vconcat )
  251. X     ( LCM       . calcFunc-lcm )
  252. X     ( Log       . calcFunc-ln )
  253. X     ( Max       . calcFunc-max )
  254. X     ( Min       . calcFunc-min )
  255. X     ( Mod       . calcFunc-mod )
  256. X     ( MoebiusMu   . calcFunc-moebius )
  257. X     ( Random       . calcFunc-random )
  258. X     ( Round       . calcFunc-round )
  259. X     ( Re       . calcFunc-re )
  260. X     ( Sign       . calcFunc-sign )
  261. X     ( Sin       . calcFunc-sin )
  262. X     ( Sinh       . calcFunc-sinh )
  263. X     ( Sqrt       . calcFunc-sqrt )
  264. X     ( Tan       . calcFunc-tan )
  265. X     ( Tanh       . calcFunc-tanh )
  266. X     ( Transpose   . calcFunc-trn )
  267. X     ( Length       . calcFunc-vlen )
  268. X))
  269. X
  270. X(put 'math 'math-variable-table
  271. X  '( ( I       . var-i )
  272. X     ( Pi       . var-pi )
  273. X     ( E       . var-e )
  274. X))
  275. X
  276. X(put 'math 'math-vector-brackets "{}")
  277. X(put 'math 'math-complex-format 'I)
  278. X(put 'math 'math-function-open "[")
  279. X(put 'math 'math-function-close "]")
  280. X
  281. X(put 'math 'math-radix-formatter
  282. X     (function (lambda (r s) (format "%d^^%s" r s))))
  283. X
  284. X
  285. X
  286. X
  287. X;;; Combinatorics
  288. X
  289. X(defun calc-k-prefix-help ()
  290. X  (interactive)
  291. X  (calc-do-prefix-help
  292. X   '("GCD, LCM; Binomial, Dbl-fact; Random, random-Again"
  293. X     "Factors, Prime-test, Next-prime, Totient, Moebius"
  294. X     "SHIFT + extended-GCD")
  295. X   "combinatorics" ?k)
  296. X)
  297. X
  298. X(defun calc-gcd (arg)
  299. X  "Compute the GCD of the top two elements of the Calculator stack."
  300. X  (interactive "P")
  301. X  (calc-slow-wrapper
  302. X   (calc-binary-op "gcd" 'calcFunc-gcd arg))
  303. X)
  304. X
  305. X(defun calc-lcm (arg)
  306. X  "Compute the LCM of the top two elements of the Calculator stack."
  307. X  (interactive "P")
  308. X  (calc-slow-wrapper
  309. X   (calc-binary-op "lcm" 'calcFunc-lcm arg))
  310. X)
  311. X
  312. X(defun calc-extended-gcd ()
  313. X  "Compute the extended GCD of the top two elements of the Calculator stack.
  314. XThis is a list [g,a,b] where g = gcd(x,y) = ax + by, and x and y are the
  315. Xsecond-to-top and top values on the stack, respectively."
  316. X  (interactive)
  317. X  (calc-slow-wrapper
  318. X   (calc-enter-result 2 "egcd" (cons 'calcFunc-egcd (calc-top-list-n 2))))
  319. X)
  320. X
  321. X(defun calc-factorial (arg)
  322. X  "Compute the factorial of the number on the top of the Calculator stack.
  323. XIf the number is an integer, computes an exact result.
  324. XIf the number is floating-point, computes a floating-point approximate result."
  325. X  (interactive "P")
  326. X  (calc-slow-wrapper
  327. X   (calc-unary-op "fact" 'calcFunc-fact arg))
  328. X)
  329. X
  330. X(defun calc-gamma (arg)
  331. X  "Compute the Euler Gamma function of the number on the Calculator stack."
  332. X  (interactive "P")
  333. X  (calc-slow-wrapper
  334. X   (calc-unary-op "gmma" 'calcFunc-gamma arg))
  335. X)
  336. X
  337. X(defun calc-double-factorial (arg)
  338. X  "Compute the double factorial of the number on the Calculator stack.
  339. XFor even numbers, this is the product of even integers up to N.
  340. XFor odd numbers, this is the product of odd integers up to N.
  341. XIf the number is an integer, computes an exact result.
  342. XIf the number is floating-point, computes a floating-point approximate result."
  343. X  (interactive "P")
  344. X  (calc-slow-wrapper
  345. X   (calc-unary-op "dfac" 'calcFunc-dfact arg))
  346. X)
  347. X
  348. X(defun calc-choose (arg)
  349. X  "Compute the binomial coefficient C(N,M) of the numbers on the stack.
  350. XIf the numbers are integers, computes an exact result.
  351. XIf either number is floating-point, computes an approximate result.
  352. XWith Hyperbolic flag, computes number-of-permutations instead."
  353. X  (interactive "P")
  354. X  (calc-slow-wrapper
  355. X   (if (calc-is-hyperbolic)
  356. X       (calc-binary-op "perm" 'calcFunc-perm arg)
  357. X     (calc-binary-op "chos" 'calcFunc-choose arg)))
  358. X)
  359. X
  360. X(defun calc-perm (arg)
  361. X  "Compute the number-of-permutations P(N,M) of the numbers on the stack.
  362. XIf the numbers are integers, computes an exact result.
  363. XIf either number is floating-point, computes an approximate result.
  364. XWith Hyperbolic flag, computes binomial coefficient instead."
  365. X  (interactive "P")
  366. X  (calc-hyperbolic-func)
  367. X  (calc-choose arg)
  368. X)
  369. X
  370. X(defvar calc-last-random-limit '(float 1 0))
  371. X(defun calc-random (n)
  372. X  "Produce a random integer between 0 (inclusive) and N (exclusive).
  373. XN is the numeric prefix argument, if any, otherwise it is taken from the stack.
  374. XIf N is real, produce a random real number in the specified range.
  375. XIf N is zero, produce a Gaussian-distributed value with mean 0, variance 1."
  376. X  (interactive "P")
  377. X  (calc-slow-wrapper
  378. X   (if n
  379. X       (calc-enter-result 0 "rand" (list 'calcFunc-random
  380. X                     (setq calc-last-random-limit
  381. X                           (prefix-numeric-value n))))
  382. X     (calc-enter-result 1 "rand" (list 'calcFunc-random
  383. X                       (setq calc-last-random-limit
  384. X                         (calc-top-n 1))))))
  385. X)
  386. X
  387. X(defun calc-rrandom ()
  388. X  "Produce a random real between 0 and 1."
  389. X  (interactive)
  390. X  (calc-slow-wrapper
  391. X   (setq calc-last-random-limit '(float 1 0))
  392. X   (calc-enter-result 0 "rand" (list 'calcFunc-random '(float 1 0))))
  393. X)
  394. X
  395. X(defun calc-random-again ()
  396. X  "Produce another random number in the same range as the last one generated."
  397. X  (interactive)
  398. X  (calc-slow-wrapper
  399. X   (calc-enter-result 0 "rand" (list 'calcFunc-random calc-last-random-limit)))
  400. X)
  401. X
  402. X(defun calc-report-prime-test (res)
  403. X  (cond ((eq (car res) t)
  404. X     (calc-record-message "prim" "Prime (guaranteed)"))
  405. X    ((eq (car res) nil)
  406. X     (if (cdr res)
  407. X         (if (eq (nth 1 res) 'unknown)
  408. X         (calc-record-message
  409. X          "prim" "Non-prime (factors unknown)")
  410. X           (calc-record-message
  411. X        "prim" "Non-prime (%s is a factor)"
  412. X        (math-format-number (nth 1 res))))
  413. X       (calc-record-message "prim" "Non-prime")))
  414. X    (t
  415. X     (calc-record-message
  416. X      "prim" "Probably prime (%d iters; %s%% chance of error)"
  417. X      (nth 1 res)
  418. X      (let ((calc-float-format '(fix 2)))
  419. X        (math-format-number (nth 2 res))))))
  420. X)
  421. X
  422. X(defun calc-prime-test (iters)
  423. X  "Determine whether the number on the top of the stack is prime.
  424. XFor large numbers (> 8 million), this test is probabilistic.
  425. XExecute this command repeatedly to improve certainty of result.
  426. XWith a numeric prefix argument, execute (up to) N iterations at once."
  427. X  (interactive "p")
  428. X  (calc-slow-wrapper
  429. X   (let* ((n (calc-top-n 1))
  430. X      (res (math-prime-test n iters)))
  431. X     (calc-report-prime-test res)))
  432. X)
  433. X
  434. X(defun calc-next-prime (iters)
  435. X  "Determine the next prime greater than the number on the top of the stack.
  436. XThe top-of-stack is replaced by this number.
  437. XFor numbers above 8 million, this finds the next number that passes one
  438. Xiteration of calc-prime-test.  With a prefix argument, the number must
  439. Xpass the specified number of calc-prime-test iterations.
  440. XWith Inverse flag, find the previous prime instead."
  441. X  (interactive "p")
  442. X  (calc-slow-wrapper
  443. X   (let ((calc-verbose-nextprime t))
  444. X     (if (calc-is-inverse)
  445. X     (calc-enter-result 1 "prvp" (list 'calcFunc-prevprime
  446. X                       (calc-top-n 1) (math-abs iters)))
  447. X       (calc-enter-result 1 "nxtp" (list 'calcFunc-nextprime
  448. X                     (calc-top-n 1) (math-abs iters))))))
  449. X)
  450. X
  451. X(defun calc-prev-prime (iters)
  452. X  "Determine the next prime less than the number on the top of the stack.
  453. XWith Inverse flag, find the next greater prime instead."
  454. X  (interactive "p")
  455. X  (calc-invert-func)
  456. X  (calc-next-prime iters)
  457. X)
  458. X
  459. X(defun calc-prime-factors (iters)
  460. X  "Attempt to reduce the integer at top of stack to a list of its prime factors.
  461. XThis algorithm is guaranteed for N up to 25 million.  For larger N, it may
  462. Xnot find all of the prime factors."
  463. X  (interactive "p")
  464. X  (calc-slow-wrapper
  465. X   (let ((res (math-prime-factors (calc-top-n 1))))
  466. X     (if (not math-prime-factors-finished)
  467. X     (calc-record-message "pfac" "Warning:  May not be fully factored"))
  468. X     (calc-enter-result 1 "pfac" res)))
  469. X)
  470. X
  471. X(defun calc-totient (arg)
  472. X  "Compute the Euler Totient function phi(n).
  473. XThis is the number of integers less than n which are relatively prime to n."
  474. X  (interactive "P")
  475. X  (calc-slow-wrapper
  476. X   (calc-unary-op "phi" 'calcFunc-totient arg))
  477. X)
  478. X
  479. X(defun calc-moebius (arg)
  480. X  "Compute the Moebius Mu function mu(n).
  481. XThis is (-1)^k if n has k distinct prime factors, or 0 if n has some
  482. Xduplicate factors."
  483. X  (interactive "P")
  484. X  (calc-slow-wrapper
  485. X   (calc-unary-op "mu" 'calcFunc-moebius arg))
  486. X)
  487. X
  488. X
  489. X
  490. X
  491. X;;; Mode commands.
  492. X
  493. X(defun calc-m-prefix-help ()
  494. X  (interactive)
  495. X  (calc-do-prefix-help
  496. X   '("Deg, Rad, HMS; Frac; Polar; Algebraic; Symbolic"
  497. X     "Working; Xtensions; M=save"
  498. X     "SHIFT + simplify: Off, Num, Default, Bin-clip, Alg, Units")
  499. X   "mode" ?m)
  500. X)
  501. X
  502. X(defun calc-save-modes ()
  503. X  "Save all mode variables' values in your .emacs file."
  504. X  (interactive)
  505. X  (calc-wrapper
  506. X   (let (pos
  507. X     (vals (mapcar (function (lambda (v) (symbol-value (car v))))
  508. X               calc-mode-var-list)))
  509. X     (set-buffer (find-file-noselect (substitute-in-file-name
  510. X                      calc-settings-file)))
  511. X     (goto-char (point-min))
  512. X     (if (and (search-forward ";;; Mode settings stored by Calc" nil t)
  513. X          (progn
  514. X        (beginning-of-line)
  515. X        (setq pos (point))
  516. X        (search-forward "\n;;; End of mode settings" nil t)))
  517. X     (progn
  518. X       (beginning-of-line)
  519. X       (forward-line 1)
  520. X       (delete-region pos (point)))
  521. X       (goto-char (point-max))
  522. X       (insert "\n\n")
  523. X       (forward-char -1))
  524. X     (insert ";;; Mode settings stored by Calc on " (current-time-string) "\n")
  525. X     (let ((list calc-mode-var-list))
  526. X       (while list
  527. X     (let* ((v (car (car list)))
  528. X        (def (nth 1 (car list)))
  529. X        (val (car vals)))
  530. X       (or (equal val def)
  531. X           (progn
  532. X         (insert "(setq " (symbol-name v) " ")
  533. X         (if (and (or (listp val)
  534. X                  (symbolp val))
  535. X              (not (memq val '(nil t))))
  536. X             (insert "'"))
  537. X         (insert (prin1-to-string val) ")\n"))))
  538. X     (setq list (cdr list)
  539. X           vals (cdr vals))))
  540. X     (run-hooks 'calc-mode-save-hook)
  541. X     (insert ";;; End of mode settings\n")
  542. X     (save-buffer)))
  543. X)
  544. X
  545. X(defun calc-algebraic-mode ()
  546. X  "Turn Algebraic mode on or off.
  547. XIn algebraic mode, numeric entry accepts whole expressions without needing \"'\"."
  548. X  (interactive)
  549. X  (calc-wrapper
  550. X   (setq calc-algebraic-mode (not calc-algebraic-mode)))
  551. X)
  552. X
  553. X(defun calc-symbolic-mode ()
  554. X  "Turn Symbolic mode on or off.
  555. XIn symbolic mode, inexact numeric computations like sqrt(2) are postponed."
  556. X  (interactive)
  557. X  (calc-wrapper
  558. X   (setq calc-symbolic-mode (not calc-symbolic-mode)))
  559. X)
  560. X
  561. X(defun calc-set-simplify-mode (mode arg)
  562. X  (setq calc-simplify-mode (if arg
  563. X                   (and (> (prefix-numeric-value arg) 0)
  564. X                    mode)
  565. X                 (and (not (eq calc-simplify-mode mode))
  566. X                  mode)))
  567. X)
  568. X
  569. X(defun calc-no-simplify-mode (arg)
  570. X  "Turn off automatic simplification of algebraic expressions."
  571. X  (interactive "P")
  572. X  (calc-wrapper
  573. X   (calc-set-simplify-mode 'none arg))
  574. X)
  575. X
  576. X(defun calc-num-simplify-mode (arg)
  577. X  "Enable automatic simplification of expressions with constant argments only."
  578. X  (interactive "P")
  579. X  (calc-wrapper
  580. X   (calc-set-simplify-mode 'num arg))
  581. X)
  582. X
  583. X(defun calc-default-simplify-mode ()
  584. X  "Turn on default automatic simplification of algebraic expressions."
  585. X  (interactive)
  586. X  (calc-wrapper
  587. X   (setq calc-simplify-mode nil))
  588. X)
  589. X
  590. X(defun calc-bin-simplify-mode (arg)
  591. X  "Turn on automatic simplification with math-clip."
  592. X  (interactive "P")
  593. X  (calc-wrapper
  594. X   (calc-set-simplify-mode 'binary arg))
  595. X)
  596. X
  597. X(defun calc-alg-simplify-mode (arg)
  598. X  "Turn on automatic algebraic simplification of expressions."
  599. X  (interactive "P")
  600. X  (calc-wrapper
  601. X   (calc-set-simplify-mode 'alg arg))
  602. X)
  603. X
  604. X(defun calc-ext-simplify-mode (arg)
  605. X  "Turn on automatic \"extended\" algebraic simplification of expressions."
  606. X  (interactive "P")
  607. X  (calc-wrapper
  608. X   (calc-set-simplify-mode 'ext arg))
  609. X)
  610. X
  611. X(defun calc-units-simplify-mode (arg)
  612. X  "Turn on automatic units-simplification of expressions."
  613. X  (interactive "P")
  614. X  (calc-wrapper
  615. X   (calc-set-simplify-mode 'units arg))
  616. X)
  617. X
  618. X(defun calc-working (n)
  619. X  "Display level of \"Working...\" messages, or set level to N.
  620. XWith numeric prefix argument 0, disables messages.
  621. XWith argument 1, enables messages.
  622. XWith argument 2, enables more detailed messages."
  623. X  (interactive "P")
  624. X  (calc-wrapper
  625. X   (cond ((consp n)
  626. X      (calc-pop-push-record 0 "work"
  627. X                (cond ((eq calc-display-working-message t) 1)
  628. X                      (calc-display-working-message 2)
  629. X                      (t 0))))
  630. X     ((eq n 2) (setq calc-display-working-message 'lots))
  631. X     ((eq n 0) (setq calc-display-working-message nil))
  632. X     ((eq n 1) (setq calc-display-working-message t)))
  633. X   (cond ((eq calc-display-working-message t)
  634. X      (message "\"Working...\" messages enabled."))
  635. X     (calc-display-working-message
  636. X      (message "Detailed \"Working...\" messages enabled."))
  637. X     (t
  638. X      (message "\"Working...\" messages disabled."))))
  639. X)
  640. X
  641. X(defun calc-always-load-extensions ()
  642. X  "Toggle mode in which calc-ext extensions are loaded automatically with calc."
  643. X  (interactive)
  644. X  (calc-wrapper
  645. X   (if (setq calc-always-load-extensions (not calc-always-load-extensions))
  646. X       (message "Always loading extensions package.")
  647. X     (message "Loading extensions package on demand only.")))
  648. X)
  649. X
  650. X(defun calc-degrees-mode ()
  651. X  "Set Calculator to use degrees for all angles."
  652. X  (interactive)
  653. X  (calc-wrapper
  654. X   (setq calc-angle-mode 'deg)
  655. X   (message "Angles measured in degrees."))
  656. X)
  657. X
  658. X(defun calc-radians-mode ()
  659. X  "Set Calculator to use degrees for all angles."
  660. X  (interactive)
  661. X  (calc-wrapper
  662. X   (setq calc-angle-mode 'rad)
  663. X   (message "Angles measured in radians."))
  664. X)
  665. X
  666. X(defun calc-hms-mode ()
  667. X  "Set Calculator to use degrees-minutes-seconds for all angles."
  668. X  (interactive)
  669. X  (calc-wrapper
  670. X   (setq calc-angle-mode 'hms)
  671. X   (message "Angles measured in degrees-minutes-seconds."))
  672. X)
  673. X
  674. X(defun calc-polar-mode (n)
  675. X  "Toggle mode complex number preference between rectangular and polar forms."
  676. X  (interactive "P")
  677. X  (calc-wrapper
  678. X   (if (if n
  679. X       (> (prefix-numeric-value n) 0)
  680. X     (eq calc-complex-mode 'cplx))
  681. X       (progn
  682. X     (setq calc-complex-mode 'polar)
  683. X     (message "Preferred complex form is polar."))
  684. X     (setq calc-complex-mode 'cplx)
  685. X     (message "Preferred complex form is rectangular.")))
  686. X)
  687. X
  688. X(defun calc-frac-mode (n)
  689. X  "Toggle mode in which Calculator prefers fractions over floats.
  690. XWith positive prefix argument, sets mode on (fractions).
  691. XWith negative or zero prefix argument, sets mode off (floats)."
  692. X  (interactive "P")
  693. X  (calc-wrapper
  694. X   (if (if n
  695. X       (> (prefix-numeric-value n) 0)
  696. X     (not calc-prefer-frac))
  697. X       (progn
  698. X     (setq calc-prefer-frac t)
  699. X     (message "Integer division will now generate fractions."))
  700. X     (setq calc-prefer-frac nil)
  701. X     (message "Integer division will now generate floating-point results.")))
  702. X)
  703. X
  704. X
  705. X
  706. X
  707. X;;; Trail commands.
  708. X
  709. X(defun calc-t-prefix-help ()
  710. X  (interactive)
  711. X  (calc-do-prefix-help
  712. X   '("Display; Fwd, Back; Next, Prev, Here, [, ]; Yank"
  713. X     "Search, Reverse; In, Out; <, >; Kill; Marker")
  714. X   "trail" ?t)
  715. X)
  716. X
  717. X(defun calc-trail-in ()
  718. X  "Switch to the Calc Trail window."
  719. X  (interactive)
  720. X  (let ((win (get-buffer-window (calc-trail-display t))))
  721. X    (and win (select-window win)))
  722. X)
  723. X
  724. X(defun calc-trail-out ()
  725. X  "Switch back to the main Calculator window."
  726. X  (interactive)
  727. X  (calc-select-buffer)
  728. X  (let ((win (get-buffer-window (current-buffer))))
  729. X    (if win
  730. X    (select-window win)
  731. X      (calc)))
  732. X)
  733. X
  734. X(defmacro calc-with-trail-buffer (&rest body)
  735. X  (` (let ((save-buf (current-buffer))
  736. X       (calc-command-flags nil))
  737. X       (unwind-protect
  738. X       (, (append '(progn
  739. X             (set-buffer (calc-trail-display t))
  740. X             (or (eq major-mode 'calc-trail-mode)
  741. X                 (error "Calc Trail buffer is not usable"))
  742. X             (goto-char calc-trail-pointer))
  743. X              body))
  744. X     (set-buffer save-buf))))
  745. X)
  746. X
  747. X(defun calc-trail-next (n)
  748. X  "Move the trail pointer down one line."
  749. X  (interactive "p")
  750. X  (calc-with-trail-buffer
  751. X   (forward-line n)
  752. X   (calc-trail-here))
  753. X)
  754. X
  755. X(defun calc-trail-previous (n)
  756. X  "Move the trail pointer up one line."
  757. X  (interactive "p")
  758. X  (calc-with-trail-buffer
  759. X   (forward-line (- n))
  760. X   (calc-trail-here))
  761. X)
  762. X
  763. X(defun calc-trail-first (n)
  764. X  "Move the trail pointer to the beginning of the trail."
  765. X  (interactive "p")
  766. X  (calc-with-trail-buffer
  767. X   (goto-char (point-min))
  768. X   (forward-line n)
  769. X   (calc-trail-here))
  770. X)
  771. X
  772. X(defun calc-trail-last (n)
  773. X  "Move the trail pointer to the end of the trail."
  774. X  (interactive "p")
  775. X  (calc-with-trail-buffer
  776. X   (goto-char (point-max))
  777. X   (forward-line (- n))
  778. X   (calc-trail-here))
  779. X)
  780. X
  781. X(defun calc-trail-scroll-left (n)
  782. X  "Scroll the trail window horizontally to the left."
  783. X  (interactive "P")
  784. X  (let ((curwin (selected-window)))
  785. X    (calc-with-trail-buffer
  786. X     (unwind-protect
  787. X     (progn
  788. X       (select-window (get-buffer-window (current-buffer)))
  789. X       (calc-scroll-left n))
  790. X       (select-window curwin))))
  791. X)
  792. X
  793. X(defun calc-trail-scroll-right (n)
  794. X  "Scroll the trail window horizontally to the right."
  795. X  (interactive "P")
  796. X  (let ((curwin (selected-window)))
  797. X    (calc-with-trail-buffer
  798. X     (unwind-protect
  799. X     (progn
  800. X       (select-window (get-buffer-window (current-buffer)))
  801. X       (calc-scroll-right n))
  802. X       (select-window curwin))))
  803. X)
  804. X
  805. X(defun calc-trail-forward (n)
  806. X  "Move the trail pointer forward one page."
  807. X  (interactive "p")
  808. X  (calc-with-trail-buffer
  809. X   (forward-line (* n (1- (window-height))))
  810. X   (calc-trail-here))
  811. X)
  812. X
  813. X(defun calc-trail-backward (n)
  814. X  "Move the trail pointer backward one page."
  815. X  (interactive "p")
  816. X  (calc-with-trail-buffer
  817. X   (forward-line (- (* n (1- (window-height)))))
  818. X   (calc-trail-here))
  819. X)
  820. X
  821. X(defun calc-trail-isearch-forward ()
  822. X  "Search incrementally forward in the trail buffer."
  823. X  (interactive)
  824. X  (calc-with-trail-buffer
  825. X   (save-window-excursion
  826. X     (select-window (get-buffer-window (current-buffer)))
  827. X     (isearch t nil))
  828. X   (calc-trail-here))
  829. X)
  830. X
  831. X(defun calc-trail-isearch-backward ()
  832. X  "Search incrementally backward in the trail buffer."
  833. X  (interactive)
  834. X  (calc-with-trail-buffer
  835. X   (save-window-excursion
  836. X     (select-window (get-buffer-window (current-buffer)))
  837. X     (isearch nil nil))
  838. X   (calc-trail-here))
  839. X)
  840. X
  841. X(defun calc-trail-yank ()
  842. X  "Yank the value indicated by the trail pointer onto the Calculator stack."
  843. X  (interactive)
  844. X  (calc-wrapper
  845. X   (calc-set-command-flag 'hold-trail)
  846. X   (calc-enter-result 0 "yank"
  847. X              (calc-with-trail-buffer
  848. X               (if (or (looking-at "Emacs Calc")
  849. X                   (looking-at "----")
  850. X                   (looking-at " ? ? ?[^ \n]* *$")
  851. X                   (looking-at "..?.?$"))
  852. X               (error "Can't yank that line"))
  853. X               (forward-char 4)
  854. X               (search-forward " ")
  855. X               (let* ((next (save-excursion (forward-line 1) (point)))
  856. X                  (str (buffer-substring (point) (1- next)))
  857. X                  (calc-language nil)
  858. X                  (math-expr-opers math-standard-opers)
  859. X                  (val (math-read-expr str)))
  860. X             (if (eq (car-safe val) 'error)
  861. X                 (error "Can't yank that line: " (nth 2 val))
  862. X               val)))))
  863. X)
  864. X
  865. X(defun calc-trail-marker (str)
  866. X  "Put a textual marker into the Calculator trail."
  867. X  (interactive "sText to insert in trail: ")
  868. X  (calc-with-trail-buffer
  869. X   (forward-line 1)
  870. X   (let ((buffer-read-only nil))
  871. X     (insert "---- " str "\n"))
  872. X   (forward-line -1)
  873. X   (calc-trail-here))
  874. X)
  875. X
  876. X(defun calc-trail-kill (n)
  877. X  "Kill one line from the Calculator trail.
  878. XThis line can be yanked into text buffers, but cannot be yanked back into
  879. Xthe trail."
  880. X  (interactive "p")
  881. X  (calc-with-trail-buffer
  882. X   (let ((buffer-read-only nil))
  883. X     (save-restriction
  884. X       (narrow-to-region   ; don't delete "Emacs Trail" header
  885. X    (save-excursion
  886. X      (goto-char (point-min))
  887. X      (forward-line 1)
  888. X      (point))
  889. X    (point-max))
  890. X       (kill-line n)))
  891. X   (calc-trail-here))
  892. X)
  893. X
  894. X
  895. X
  896. X;;; Units commands.
  897. X
  898. X(defun calc-u-prefix-help ()
  899. X  (interactive)
  900. X  (calc-do-prefix-help
  901. X   '("Simplify, Convert, Temperature-convert, Base-units"
  902. X     "Remove, eXtract; Explain; View-table"
  903. X     "Define, Undefine, Get-defn, Permanent")
  904. X   "units" ?u)
  905. X)
  906. X
  907. X(defun calc-base-units ()
  908. X  "Convert the value on the stack into \"base\" units, like m, g, and s."
  909. X  (interactive)
  910. X  (calc-slow-wrapper
  911. X   (calc-enter-result 1 "bsun" (math-simplify-units
  912. X                (math-to-standard-units (calc-top-n 1) nil))))
  913. X)
  914. X
  915. X(defun calc-convert-units (&optional old-units new-units)
  916. X  "Convert the value on the stack to the specified new units.
  917. XUnit name may also be \"si\", \"mks\", or \"cgs\" to convert to that system.
  918. XTemperature units are converted as relative temperatures."
  919. X  (interactive)
  920. X  (calc-slow-wrapper
  921. X   (let ((expr (calc-top-n 1))
  922. X     (uoldname nil)
  923. X     unew)
  924. X     (or (math-units-in-expr-p expr t)
  925. X     (let ((uold (or old-units
  926. X             (progn
  927. X               (setq uoldname (read-string "Old units: "))
  928. X               (if (equal uoldname "")
  929. X                   (progn
  930. X                 (setq uoldname "1")
  931. X                 1)
  932. X                 (math-read-expr uoldname))))))
  933. X       (if (eq (car-safe uold) 'error)
  934. X           (error "Bad format in units expression: %s" (nth 1 uold)))
  935. X       (setq expr (math-mul expr uold))))
  936. X     (or new-units
  937. X     (setq new-units (read-string (if uoldname
  938. X                      (concat "Old units: "
  939. X                          uoldname
  940. X                          ", new units: ")
  941. X                    "New units: "))))
  942. X     (setq units (math-read-expr new-units))
  943. X     (if (eq (car-safe units) 'error)
  944. X     (error "Bad format in units expression: %s" (nth 2 units)))
  945. X     (let ((unew (math-units-in-expr-p units t))
  946. X       (std (and (eq (car-safe units) 'var)
  947. X             (assq (nth 1 units) math-standard-units-systems))))
  948. X       (if std
  949. X       (calc-enter-result 1 "cvun" (math-simplify-units
  950. X                    (math-to-standard-units expr
  951. X                                (nth 1 std))))
  952. X     (or unew
  953. X         (error "No units specified"))
  954. X     (calc-enter-result 1 "cvun" (math-simplify-units
  955. X                      (math-convert-units expr units)))))))
  956. X)
  957. X
  958. X(defun calc-convert-temperature (&optional old-units new-units)
  959. X  "Convert the value on the stack to the specified new temperature units.
  960. XThis converts absolute temperature, i.e., \"0 degC\" converts to \"32 degF\"."
  961. X  (interactive)
  962. X  (calc-slow-wrapper
  963. X   (let ((expr (calc-top-n 1))
  964. X     (uold nil)
  965. X     (uoldname nil)
  966. X     unew)
  967. X     (setq uold (or old-units
  968. X            (let ((units (math-single-units-in-expr-p expr)))
  969. X              (if units
  970. X              (if (consp units)
  971. X                  (list 'var (car units)
  972. X                    (intern (concat "var-"
  973. X                            (symbol-name
  974. X                             (car units)))))
  975. X                (error "Not a pure temperature expression"))
  976. X            (math-read-expr
  977. X             (setq uoldname (read-string
  978. X                     "Old temperature units: ")))))))
  979. X     (if (eq (car-safe uold) 'error)
  980. X     (error "Bad format in units expression: %s" (nth 2 uold)))
  981. X     (or (math-units-in-expr-p expr nil)
  982. X     (setq expr (math-mul expr uold)))
  983. X     (setq unew (or new-units
  984. X            (math-read-expr
  985. X             (read-string (if uoldname
  986. X                      (concat "Old temperature units: "
  987. X                          uoldname
  988. X                          ", new units: ")
  989. X                    "New temperature units: ")))))
  990. X     (if (eq (car-safe unew) 'error)
  991. X     (error "Bad format in units expression: %s" (nth 2 unew)))
  992. X     (calc-enter-result 1 "cvtm" (math-simplify-units
  993. X                  (math-convert-temperature expr uold unew)))))
  994. X)
  995. X
  996. X(defun calc-remove-units ()
  997. X  "Remove all unit names from the value on the top of the stack."
  998. X  (interactive)
  999. X  (calc-slow-wrapper
  1000. X   (calc-enter-result 1 "rmun" (math-simplify-units
  1001. X                (math-remove-units (calc-top-n 1)))))
  1002. X)
  1003. X
  1004. X(defun calc-extract-units ()
  1005. X  "Extract the units from the unit expression on the top of the stack."
  1006. X  (interactive)
  1007. X  (calc-slow-wrapper
  1008. X   (calc-enter-result 1 "rmun" (math-simplify-units
  1009. X                (math-extract-units (calc-top-n 1)))))
  1010. X)
  1011. X
  1012. X(defun calc-explain-units ()
  1013. X  "Produce an English explanation of the units of the expression on the stack."
  1014. X  (interactive)
  1015. X  (calc-wrapper
  1016. X   (let ((num-units nil)
  1017. X     (den-units nil))
  1018. X     (calc-explain-units-rec (calc-top-n 1) 1)
  1019. X     (and den-units (string-match "^[^(].* .*[^)]$" den-units)
  1020. X      (setq den-units (concat "(" den-units ")")))
  1021. X     (if num-units
  1022. X     (if den-units
  1023. X         (message "%s per %s" num-units den-units)
  1024. X       (message "%s" num-units))
  1025. X       (if den-units
  1026. X       (message "1 per %s" den-units)
  1027. X     (message "No units in expression")))))
  1028. X)
  1029. X
  1030. X(defun calc-explain-units-rec (expr pow)
  1031. X  (let ((u (math-check-unit-name expr))
  1032. X    pos)
  1033. X    (if (and u (not (math-zerop pow)))
  1034. X    (let ((name (or (nth 2 u) (symbol-name (car u)))))
  1035. X      (if (eq (aref name 0) ?\*)
  1036. X          (setq name (substring name 1)))
  1037. X      (if (string-match "[^a-zA-Z0-9']" name)
  1038. X          (if (string-match "^[a-zA-Z0-9' ()]*$" name)
  1039. X          (while (setq pos (string-match "[ ()]" name))
  1040. X            (setq name (concat (substring name 0 pos)
  1041. X                       (if (eq (aref name pos) 32) "-" "")
  1042. X                       (substring name (1+ pos)))))
  1043. X        (setq name (concat "(" name ")"))))
  1044. X      (or (eq (nth 1 expr) (car u))
  1045. X          (setq name (concat (nth 2 (assq (aref (symbol-name
  1046. X                             (nth 1 expr)) 0)
  1047. X                          math-unit-prefixes))
  1048. X                 (if (and (string-match "[^a-zA-Z0-9']" name)
  1049. X                      (not (memq (car u) '(mHg gf))))
  1050. X                     (concat "-" name)
  1051. X                   (downcase name)))))
  1052. X      (cond ((or (math-equal-int pow 1)
  1053. X             (math-equal-int pow -1)))
  1054. X        ((or (math-equal-int pow 2)
  1055. X             (math-equal-int pow -2))
  1056. X         (if (equal (nth 4 u) '((m . 1)))
  1057. X             (setq name (concat "Square-" name))
  1058. X           (setq name (concat name "-squared"))))
  1059. X        ((or (math-equal-int pow 3)
  1060. X             (math-equal-int pow -3))
  1061. X         (if (equal (nth 4 u) '((m . 1)))
  1062. X             (setq name (concat "Cubic-" name))
  1063. X           (setq name (concat name "-cubed"))))
  1064. X        (t
  1065. X         (setq name (concat name "^"
  1066. X                    (math-format-number (math-abs pow))))))
  1067. X      (if (math-posp pow)
  1068. X          (setq num-units (if num-units
  1069. X                  (concat num-units " " name)
  1070. X                name))
  1071. X        (setq den-units (if den-units
  1072. X                (concat den-units " " name)
  1073. X                  name))))
  1074. X      (cond ((eq (car-safe expr) '*)
  1075. X         (calc-explain-units-rec (nth 1 expr) pow)
  1076. X         (calc-explain-units-rec (nth 2 expr) pow))
  1077. X        ((eq (car-safe expr) '/)
  1078. X         (calc-explain-units-rec (nth 1 expr) pow)
  1079. X         (calc-explain-units-rec (nth 2 expr) (- pow)))
  1080. X        ((memq (car-safe expr) '(neg + -))
  1081. X         (calc-explain-units-rec (nth 1 expr) pow))
  1082. X        ((and (eq (car-safe expr) '^)
  1083. X          (math-realp (nth 2 expr)))
  1084. X         (calc-explain-units-rec (nth 1 expr)
  1085. X                     (math-mul pow (nth 2 expr)))))))
  1086. X)
  1087. X
  1088. X(defun calc-simplify-units ()
  1089. X  "Simplify the units expression on top of the stack."
  1090. X  (interactive)
  1091. X  (calc-slow-wrapper
  1092. X   (calc-with-default-simplification
  1093. X    (calc-enter-result 1 "smun" (math-simplify-units (calc-top-n 1)))))
  1094. X)
  1095. X
  1096. X(defun calc-view-units-table (n)
  1097. X  "Display a temporary buffer for displaying the Units Table."
  1098. X  (interactive "P")
  1099. X  (and n (setq math-units-table-buffer-valid nil))
  1100. X  (math-build-units-table-buffer nil)
  1101. X)
  1102. X
  1103. X(defun calc-enter-units-table (n)
  1104. X  "Switch to a temporary buffer for displaying the Units Table."
  1105. X  (interactive "P")
  1106. X  (and n (setq math-units-table-buffer-valid nil))
  1107. X  (math-build-units-table-buffer t)
  1108. X  (message (substitute-command-keys "Type \\[calc] to return to the Calculator."))
  1109. X)
  1110. X
  1111. X(defun calc-define-unit (uname desc)
  1112. X  "Define a new type of unit using the formula on the top of the stack."
  1113. X  (interactive "SDefine unit name: \nsDescription: ")
  1114. X  (calc-wrapper
  1115. X   (let ((form (calc-top-n 1))
  1116. X     (unit (assq uname math-additional-units)))
  1117. X     (or unit
  1118. X     (setq math-additional-units
  1119. X           (cons (setq unit (list uname nil nil))
  1120. X             math-additional-units)
  1121. X           math-units-table nil))
  1122. X     (setcar (cdr unit) (and (not (and (eq (car-safe form) 'var)
  1123. X                       (eq (nth 1 form) uname)))
  1124. X                 (not (math-equal-int form 1))
  1125. X                 (math-format-flat-expr form 0)))
  1126. X     (setcar (cdr (cdr unit)) (and (not (equal desc ""))
  1127. X                   desc))))
  1128. X  (calc-invalidate-units-table)
  1129. X)
  1130. X
  1131. X(defun calc-undefine-unit (uname)
  1132. X  "Remove the definition of a user-defined unit."
  1133. X  (interactive "SUndefine unit name: ")
  1134. X  (calc-wrapper
  1135. X   (let ((unit (assq uname math-additional-units)))
  1136. X     (or unit
  1137. X     (if (assq uname math-standard-units)
  1138. X         (error "\"%s\" is a predefined unit name" uname)
  1139. X       (error "Unit name \"%s\" not found" uname)))
  1140. X     (setq math-additional-units (delq unit math-additional-units)
  1141. X       math-units-table nil)))
  1142. X  (calc-invalidate-units-table)
  1143. X)
  1144. X
  1145. X(defun calc-invalidate-units-table ()
  1146. X  (setq math-units-table nil)
  1147. X  (let ((buf (get-buffer "*Units Table*")))
  1148. X    (save-excursion
  1149. X      (set-buffer buf)
  1150. X      (save-excursion
  1151. X    (goto-char (point-min))
  1152. X    (if (looking-at "Calculator Units Table")
  1153. X        (let ((buffer-read-only nil))
  1154. X          (insert "(Obsolete) "))))))
  1155. X)
  1156. X
  1157. X(defun calc-get-unit-definition (uname)
  1158. X  "Push the definition of a unit as a formula on the Calculator stack."
  1159. X  (interactive "SGet definition for unit: ")
  1160. X  (calc-wrapper
  1161. X   (math-build-units-table)
  1162. X   (let ((unit (assq uname math-units-table)))
  1163. X     (or unit
  1164. X     (error "Unit name \"%s\" not found" uname))
  1165. X     (let ((msg (nth 2 unit)))
  1166. X       (if (stringp msg)
  1167. X       (if (string-match "^\\*" msg)
  1168. X           (setq msg (substring msg 1)))
  1169. X     (setq msg (symbol-name uname)))
  1170. X       (if (nth 1 unit)
  1171. X       (progn
  1172. X         (calc-enter-result 0 "ugdf" (nth 1 unit))
  1173. X         (message "Derived unit: %s" msg))
  1174. X     (calc-enter-result 0 "ugdf" (list 'var uname
  1175. X                       (intern
  1176. X                        (concat "var-"
  1177. X                            (symbol-name uname)))))
  1178. X     (message "Base unit: %s" msg)))))
  1179. X)
  1180. X
  1181. X(defun calc-permanent-units ()
  1182. X  "Save all user-defined units in your .emacs file."
  1183. X  (interactive)
  1184. X  (calc-wrapper
  1185. X   (let (pos)
  1186. X     (set-buffer (find-file-noselect (substitute-in-file-name
  1187. X                      calc-settings-file)))
  1188. X     (goto-char (point-min))
  1189. X     (if (and (search-forward ";;; Custom units stored by Calc" nil t)
  1190. X          (progn
  1191. X        (beginning-of-line)
  1192. X        (setq pos (point))
  1193. X        (search-forward "\n;;; End of custom units" nil t)))
  1194. X     (progn
  1195. X       (beginning-of-line)
  1196. X       (forward-line 1)
  1197. X       (delete-region pos (point)))
  1198. X       (goto-char (point-max))
  1199. X       (insert "\n\n")
  1200. X       (forward-char -1))
  1201. X     (insert ";;; Custom units stored by Calc on " (current-time-string) "\n")
  1202. X     (if math-additional-units
  1203. X     (progn
  1204. X       (insert "(setq math-additional-units '(\n")
  1205. X       (let ((list math-additional-units))
  1206. X         (while list
  1207. X           (insert "  (" (symbol-name (car (car list))) " "
  1208. X               (if (nth 1 (car list))
  1209. X               (if (stringp (nth 1 (car list)))
  1210. X                   (prin1-to-string (nth 1 (car list)))
  1211. X                 (prin1-to-string (math-format-flat-expr
  1212. X                           (nth 1 (car list)) 0)))
  1213. X             "nil")
  1214. X               " "
  1215. X               (prin1-to-string (nth 2 (car list)))
  1216. X               ")\n")
  1217. X           (setq list (cdr list))))
  1218. X       (insert "))\n"))
  1219. X       (insert ";;; (no custom units defined)\n"))
  1220. X     (insert ";;; End of custom units\n")
  1221. X     (save-buffer)))
  1222. X)
  1223. X
  1224. X
  1225. X
  1226. X
  1227. X;;; Vector commands.
  1228. X
  1229. X(defun calc-v-prefix-help ()
  1230. X  (interactive)
  1231. X  (calc-do-prefix-help
  1232. X   '("Pack, Unpack, Identity, Diagonal, indeX, Build"
  1233. X     "Row, Col, Length; rNorm"
  1234. X     "Tranpose, Arrange; Sort, Histogram"
  1235. X     "SHIFT + Det, Inv, LUD, Trace, conJtrn, Cross, cNorm"
  1236. X     "SHIFT + Reduce, Map, Apply"
  1237. X     "<, =, > (justification); , (commas); [, {, ( (brackets)")
  1238. X   "vec/mat" ?v)
  1239. X)
  1240. X
  1241. X(defun calc-concat (arg)
  1242. X  "Concatenate the two vectors at the top of the stack.
  1243. XOr concatenate a scalar value and a vector."
  1244. X  (interactive "P")
  1245. X  (calc-wrapper
  1246. X   (calc-binary-op "|" 'calcFunc-vconcat arg '(vec)))
  1247. X)
  1248. X
  1249. X(defun calc-matrix-left-justify ()
  1250. X  "Left-justify elements of matrices."
  1251. X  (interactive)
  1252. X  (calc-wrapper
  1253. X   (setq calc-matrix-just nil)
  1254. X   (calc-refresh))
  1255. X)
  1256. X
  1257. X(defun calc-matrix-center-justify ()
  1258. X  "Center elements of matrices."
  1259. X  (interactive)
  1260. X  (calc-wrapper
  1261. X   (setq calc-matrix-just 'center)
  1262. X   (calc-refresh))
  1263. X)
  1264. X
  1265. X(defun calc-matrix-right-justify ()
  1266. X  "Right-justify elements of matrices."
  1267. X  (interactive)
  1268. X  (calc-wrapper
  1269. X   (setq calc-matrix-just 'right)
  1270. X   (calc-refresh))
  1271. X)
  1272. X
  1273. X(defun calc-vector-commas ()
  1274. X  "Turn separating commas in vectors on and off."
  1275. X  (interactive)
  1276. X  (calc-wrapper
  1277. X   (setq calc-vector-commas (if calc-vector-commas nil ","))
  1278. X   (calc-refresh))
  1279. X)
  1280. X
  1281. X(defun calc-vector-brackets ()
  1282. X  "Surround vectors and matrices with square brackets.
  1283. XIf already using brackets, turn the brackets off."
  1284. X  (interactive)
  1285. X  (calc-wrapper
  1286. X   (setq calc-vector-brackets (if (equal calc-vector-brackets "[]") nil "[]"))
  1287. X   (calc-refresh))
  1288. X)
  1289. X
  1290. X(defun calc-vector-braces ()
  1291. X  "Surround vectors and matrices with curly braces.
  1292. XIf already using braces, turn the braces off."
  1293. X  (interactive)
  1294. X  (calc-wrapper
  1295. X   (setq calc-vector-brackets (if (equal calc-vector-brackets "{}") nil "{}"))
  1296. X   (calc-refresh))
  1297. X)
  1298. X
  1299. X(defun calc-vector-parens ()
  1300. X  "Surround vectors and matrices with parentheses.
  1301. XIf already using parens, turn the parens off."
  1302. X  (interactive)
  1303. X  (calc-wrapper
  1304. X   (setq calc-vector-brackets (if (equal calc-vector-brackets "()") nil "()"))
  1305. X   (calc-refresh))
  1306. X)
  1307. X
  1308. X(defun calc-pack (n)
  1309. X  "Pack the top two numbers on the Calculator stack into a complex number.
  1310. XGiven a numeric prefix, pack the top N numbers into a vector.
  1311. XGiven a -1 prefix, pack the top 2 numbers into a rectangular complex number.
  1312. XGiven a -2 prefix, pack the top 2 numbers into a polar complex number.
  1313. XGiven a -3 prefix, pack the top 3 numbers into an HMS form.
  1314. XGiven a -4 prefix, pack the top 2 numbers into an error form.
  1315. XGiven a -5 prefix, pack the top 2 numbers into a modulo form.
  1316. XGiven a -6 prefix, pack the top 2 numbers into a [ .. ] interval form.
  1317. XGiven a -7 prefix, pack the top 2 numbers into a [ .. ) interval form.
  1318. XGiven a -8 prefix, pack the top 2 numbers into a ( .. ] interval form.
  1319. XGiven a -9 prefix, pack the top 2 numbers into a ( .. ) interval form."
  1320. X  (interactive "P")
  1321. X  (calc-wrapper
  1322. X   (let ((num (prefix-numeric-value n)))
  1323. X     (cond ((and n (>= num 0))
  1324. X        (calc-enter-result num nil (cons 'vec (calc-top-list num))))
  1325. X       ((= num -3)
  1326. X        (let ((h (calc-top 3))
  1327. X          (m (calc-top 2))
  1328. X          (s (calc-top 1)))
  1329. X          (if (and (math-num-integerp h)
  1330. X               (math-num-integerp m))
  1331. X          (calc-enter-result 3 nil (list 'hms h m s))
  1332. X        (error "Hours and minutes must be integers"))))
  1333. X       ((= num -4)
  1334. X        (let ((x (calc-top-n 2))
  1335. X          (sigma (calc-top-n 1)))
  1336. X          (if (and (or (math-anglep x) (not (math-objvecp x)))
  1337. X               (or (math-anglep sigma) (not (math-objvecp sigma))))
  1338. X          (calc-enter-result 2 nil (math-make-sdev x sigma))
  1339. X        (error "Components must be real"))))
  1340. X       ((= num -5)
  1341. X        (let ((a (calc-top-n 2))
  1342. X          (m (calc-top-n 1)))
  1343. X          (if (and (math-anglep a) (math-anglep m))
  1344. X          (if (math-posp m)
  1345. X              (calc-enter-result 2 nil (math-make-mod a m))
  1346. X            (error "Modulus must be positive"))
  1347. X        (error "Components must be real"))))
  1348. X       ((memq num '(-6 -7 -8 -9))
  1349. X        (let ((lo (calc-top-n 2))
  1350. X          (hi (calc-top-n 1)))
  1351. X          (if (and (or (math-anglep lo) (not (math-objvecp lo)))
  1352. X               (or (math-anglep hi) (not (math-objvecp hi))))
  1353. X          (calc-enter-result 2 nil (math-make-intv (+ num 6) lo hi))
  1354. X        (error "Components must be real"))))
  1355. X       ((or (= num -2)
  1356. X        (and (eq calc-complex-mode 'polar)
  1357. X             (= num 0)))
  1358. X        (let ((r (calc-top 2))
  1359. X          (theta (calc-top 1)))
  1360. X          (if (and (math-realp r) (math-anglep theta))
  1361. X          (calc-enter-result 2 nil (list 'polar r theta))
  1362. X        (error "Components must be real"))))
  1363. X       (t
  1364. X        (let ((real (calc-top 2))
  1365. X          (imag (calc-top 1)))
  1366. X          (if (and (math-realp real) (math-realp imag))
  1367. X          (calc-enter-result 2 nil (list 'cplx real imag))
  1368. X        (error "Components must be real")))))))
  1369. X)
  1370. X
  1371. X(defun calc-unpack ()
  1372. X  "Unpack complex number, vector, HMS form, error form, etc. at top of stack."
  1373. X  (interactive)
  1374. X  (calc-wrapper
  1375. X   (let ((num (calc-top)))
  1376. X     (if (or (and (not (memq (car-safe num) '(cplx polar vec hms sdev mod)))
  1377. X          (math-objvecp num))
  1378. X         (eq (car-safe num) 'var))
  1379. X     (error "Argument must be a vector, complex number, or HMS, error, or modulo form"))
  1380. X     (calc-pop-push-list 1 (cdr num))))
  1381. X)
  1382. X
  1383. X(defun calc-diag (n)
  1384. X  "Build an NxN element diagonal matrix out of top-of-stack.
  1385. XIf top-of-stack is a vector, numeric prefix N must match or be omitted.
  1386. XIf top-of-stack is a scalar, numeric prefix N is required."
  1387. X  (interactive "P")
  1388. X  (calc-wrapper
  1389. X   (calc-enter-result 1 "diag" (if n
  1390. X                   (list 'calcFunc-diag (calc-top-n 1)
  1391. X                     (prefix-numeric-value n))
  1392. X                 (list 'calcFunc-diag (calc-top-n 1)))))
  1393. X)
  1394. X
  1395. X(defun calc-ident (n)
  1396. X  "Push an NxN element identity matrix on the stack."
  1397. X  (interactive "NDimension of identity matrix = ")
  1398. X  (calc-wrapper
  1399. X   (calc-enter-result 0 "idn" (list 'calcFunc-diag 1
  1400. X                    (prefix-numeric-value n))))
  1401. X)
  1402. X
  1403. X(defun calc-index (n)
  1404. X  "Generate a vector of the form [1, 2, ..., N]."
  1405. X  (interactive "NSize of vector = ")
  1406. X  (calc-wrapper
  1407. X   (calc-enter-result 0 "indx" (list 'calcFunc-index
  1408. X                     (prefix-numeric-value n))))
  1409. X)
  1410. X
  1411. X(defun calc-build-vector (n)
  1412. X  "Generate a vector of N copies of top-of-stack."
  1413. X  (interactive "NSize of vector = ")
  1414. X  (calc-wrapper
  1415. X   (calc-enter-result 1 "bldv" (list 'calcFunc-cvec
  1416. X                     (calc-top-n 1)
  1417. X                     (prefix-numeric-value n))))
  1418. X)
  1419. X
  1420. X(defun calc-vlength (arg)
  1421. X  "Replace a vector with its length, in the form of an integer."
  1422. X  (interactive "P")
  1423. X  (calc-wrapper
  1424. X   (calc-unary-op "len" 'calcFunc-vlen arg))
  1425. X)
  1426. X
  1427. X(defun calc-arrange-vector (n)
  1428. X  "Rearrange a matrix to have a specific number of columns."
  1429. X  (interactive "NNumber of columns = ")
  1430. X  (calc-wrapper
  1431. X   (calc-enter-result 1 "arng" (list 'calcFunc-arrange (calc-top-n 1)
  1432. X                     (prefix-numeric-value n))))
  1433. X)
  1434. X
  1435. X(defun calc-sort ()
  1436. X  "Sort the matrix at top of stack into increasing order.
  1437. XWith Inverse flag or a negative numeric prefix, sort into decreasing order."
  1438. X  (interactive)
  1439. X  (calc-slow-wrapper
  1440. X   (if (calc-is-inverse)
  1441. X       (calc-enter-result 1 "rsrt" (list 'calcFunc-rsort (calc-top-n 1)))
  1442. X     (calc-enter-result 1 "sort" (list 'calcFunc-sort (calc-top-n 1)))))
  1443. X)
  1444. X
  1445. X(defun calc-histogram (n)
  1446. X  "Compile a histogram of a vector of integers in the range [0..N).
  1447. XN is the numeric prefix argument.
  1448. XWith Hyperbolic flag, top-of-stack is a vector of weights to associate
  1449. Xwith elements of next-to-top."
  1450. X  (interactive "NNumber of bins: ")
  1451. X  (calc-slow-wrapper
  1452. X   (if calc-hyperbolic-flag
  1453. X       (calc-enter-result 2 "hist" (list 'calcFunc-histogram
  1454. X                     (calc-top-n 2)
  1455. X                     (calc-top-n 1)
  1456. X                     (prefix-numeric-value n)))
  1457. X     (calc-enter-result 1 "hist" (list 'calcFunc-histogram
  1458. X                       (calc-top-n 1)
  1459. X                       1
  1460. X                       (prefix-numeric-value n)))))
  1461. X)
  1462. X
  1463. X(defun calc-transpose (arg)
  1464. X  "Replace the matrix at top of stack with its transpose."
  1465. X  (interactive "P")
  1466. X  (calc-wrapper
  1467. X   (calc-unary-op "trn" 'calcFunc-trn arg))
  1468. X)
  1469. X
  1470. X(defun calc-conj-transpose (arg)
  1471. X  "Replace the matrix at top of stack with its conjugate transpose."
  1472. X  (interactive "P")
  1473. X  (calc-wrapper
  1474. X   (calc-unary-op "ctrn" 'calcFunc-ctrn arg))
  1475. X)
  1476. X
  1477. X(defun calc-cross (arg)
  1478. X  "Compute the right-handed cross product of two 3-vectors."
  1479. X  (interactive "P")
  1480. X  (calc-wrapper
  1481. X   (calc-binary-op "cros" 'calcFunc-cross arg))
  1482. X)
  1483. X
  1484. X(defun calc-mdet (arg)
  1485. X  "Compute the determinant of the square matrix on the top of the stack."
  1486. X  (interactive "P")
  1487. X  (calc-slow-wrapper
  1488. X   (calc-unary-op "mdet" 'calcFunc-det arg))
  1489. X)
  1490. X
  1491. X(defun calc-mtrace (arg)
  1492. X  "Compute the trace of the square matrix on the top of the stack."
  1493. X  (interactive "P")
  1494. X  (calc-slow-wrapper
  1495. X   (calc-unary-op "mtr" 'calcFunc-tr arg))
  1496. X)
  1497. X
  1498. X(defun calc-mlud (arg)
  1499. X  "Perform an L-U decomposition of the matrix on the top of the stack.
  1500. XResult is a vector of two matrices, L and U."
  1501. X  (interactive "P")
  1502. X  (calc-slow-wrapper
  1503. X   (calc-unary-op "mlud" 'calcFunc-lud arg))
  1504. X)
  1505. X
  1506. X(defun calc-rnorm (arg)
  1507. X  "Compute the row norm of the vector or matrix on the top of the stack.
  1508. XThis is the maximum row-absolute-value-sum of the matrix.
  1509. XFor a vector, this is the maximum of the absolute values of the elements."
  1510. X  (interactive "P")
  1511. X  (calc-wrapper
  1512. X   (calc-unary-op "rnrm" 'calcFunc-rnorm arg))
  1513. X)
  1514. X
  1515. X(defun calc-cnorm (arg)
  1516. X  "Compute the column norm of the vector or matrix on the top of the stack.
  1517. XThis is the maximum column-absolute-value-sum of the matrix.
  1518. XFor a vector, this is the sum of the absolute values of the elements."
  1519. X  (interactive "P")
  1520. X  (calc-wrapper
  1521. X   (calc-unary-op "cnrm" 'calcFunc-cnorm arg))
  1522. X)
  1523. X
  1524. X(defun calc-mrow (n)
  1525. X  "Replace matrix at top of stack with its Nth row.
  1526. XNumeric prefix N must be between 1 and the height of the matrix.
  1527. XIf top of stack is a non-matrix vector, extract its Nth element.
  1528. XIf N is negative, remove the Nth row (or element)."
  1529. X  (interactive "NRow number: ")
  1530. X  (calc-wrapper
  1531. X   (setq n (prefix-numeric-value n))
  1532. X   (if (= n 0)
  1533. X       (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
  1534. X     (if (< n 0)
  1535. X     (calc-enter-result 1 "rrow" (list 'calcFunc-mrrow
  1536. X                       (calc-top-n 1) (- n)))
  1537. X       (calc-enter-result 1 "mrow" (list 'calcFunc-mrow (calc-top-n 1) n)))))
  1538. X)
  1539. X
  1540. X(defun calc-mcol (n)
  1541. X  "Replace matrix at top of stack with its Nth column.
  1542. XNumeric prefix N must be between 1 and the width of the matrix.
  1543. XIf top of stack is a non-matrix vector, extract its Nth element.
  1544. XIf N is negative, remove the Nth column (or element)."
  1545. X  (interactive "NColumn number: ")
  1546. X  (calc-wrapper
  1547. X   (setq n (prefix-numeric-value n))
  1548. X   (if (= n 0)
  1549. X       (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
  1550. X     (if (< n 0)
  1551. X     (calc-enter-result 1 "rcol" (list 'calcFunc-mrcol
  1552. X                       (calc-top-n 1) (- n)))
  1553. X       (calc-enter-result 1 "mcol" (list 'calcFunc-mcol (calc-top-n 1) n)))))
  1554. X)
  1555. X
  1556. X(defun calc-apply (&optional oper)
  1557. X  "Apply an operator to the elements of a vector.
  1558. XFor example, applying f to [1, 2, 3] produces f(1, 2, 3)."
  1559. X  (interactive)
  1560. X  (calc-wrapper
  1561. X   (let* ((calc-dollar-values (mapcar 'car-safe
  1562. X                      (nthcdr calc-stack-top calc-stack)))
  1563. X      (calc-dollar-used 0)
  1564. X      (oper (or oper (calc-get-operator "Apply"
  1565. X                        (and (math-vectorp (calc-top 1))
  1566. X                         (1- (length (calc-top 1)))))))
  1567. X      (expr (calc-top-n (1+ calc-dollar-used))))
  1568. X     (message "Working...")
  1569. X     (calc-set-command-flag 'clear-message)
  1570. X     (calc-enter-result (1+ calc-dollar-used)
  1571. X            (concat (substring "apl" 0 (- 4 (length (nth 2 oper))))
  1572. X                (nth 2 oper))
  1573. X            (list 'calcFunc-apply
  1574. X                  (math-calcFunc-to-var (nth 1 oper))
  1575. X                  expr))))
  1576. X)
  1577. X
  1578. X(defun calc-reduce (&optional oper)
  1579. X  "Apply a binary operator across all elements of a vector.
  1580. XFor example, applying + computes the sum of vector elements."
  1581. X  (interactive)
  1582. X  (calc-wrapper
  1583. X   (let* ((calc-dollar-values (mapcar 'car-safe
  1584. X                      (nthcdr calc-stack-top calc-stack)))
  1585. X      (calc-dollar-used 0)
  1586. X      (oper (or oper (calc-get-operator "Reduce" 2))))
  1587. X     (message "Working...")
  1588. X     (calc-set-command-flag 'clear-message)
  1589. X     (calc-enter-result (1+ calc-dollar-used)
  1590. X            (concat (substring "red" 0 (- 4 (length (nth 2 oper))))
  1591. X                (nth 2 oper))
  1592. X            (list (intern (concat "calcFunc-reduce"
  1593. X                          (or calc-mapping-dir "")))
  1594. X                  (math-calcFunc-to-var (nth 1 oper))
  1595. X                  (calc-top-n (1+ calc-dollar-used))))))
  1596. X)
  1597. X
  1598. X(defun calc-map (&optional oper)
  1599. X  "Apply an operator elementwise to one or two vectors.
  1600. XFor example, applying * computes a vector of products."
  1601. X  (interactive)
  1602. X  (calc-wrapper
  1603. X   (let* ((calc-dollar-values (mapcar 'car-safe
  1604. X                      (nthcdr calc-stack-top calc-stack)))
  1605. X      (calc-dollar-used 0)
  1606. X      (oper (or oper (calc-get-operator "Map")))
  1607. X      (nargs (if (or (equal calc-mapping-dir "a")
  1608. X             (equal calc-mapping-dir "d"))
  1609. X             1
  1610. X           (car oper))))
  1611. X     (message "Working...")
  1612. X     (calc-set-command-flag 'clear-message)
  1613. X     (calc-enter-result (+ nargs calc-dollar-used)
  1614. X            (concat (substring "map" 0 (- 4 (length (nth 2 oper))))
  1615. X                (nth 2 oper))
  1616. X            (cons (intern (concat "calcFunc-map"
  1617. X                          (or calc-mapping-dir "")))
  1618. X                  (cons (math-calcFunc-to-var (nth 1 oper))
  1619. X                    (calc-top-list-n
  1620. X                     nargs
  1621. X                     (1+ calc-dollar-used)))))))
  1622. X)
  1623. X
  1624. X;;; Return a list of the form (nargs func name)
  1625. X(defun calc-get-operator (msg &optional nargs)
  1626. X  (let ((inv nil) (hyp nil) (prefix nil)
  1627. X    done key oper (which 0)
  1628. X    (msgs '( "(Press ? for help)"
  1629. X         "+, -, *, /, ^, %, \\, :, !, |, Neg"
  1630. X         "SHIFT + Abs, conJ, arG; maX, miN; Floor, Round; sQrt"
  1631. X         "SHIFT + Inv, Hyp; Sin, Cos, Tan; Exp, Ln, logB"
  1632. X         "Binary + And, Or, Xor, Diff; Not, Clip"
  1633. X         "Conversions + Deg, Rad, HMS; Float; SHIFT + Fraction"
  1634. X         "Kombinatorics + Dfact, Lcm, Gcd, Binomial, Perms; Random"
  1635. X         "Matrix-dir + Elements, Rows, Cols, Across, Down"
  1636. X         "X or Z = any function by name; ' = alg entry; $ = stack")))
  1637. X    (while (not done)
  1638. X      (message "%s%s: %s: %s%s%s"
  1639. X           msg
  1640. X           (cond ((equal calc-mapping-dir "r") " rows")
  1641. X             ((equal calc-mapping-dir "c") " columns")
  1642. X             ((equal calc-mapping-dir "a") " across")
  1643. X             ((equal calc-mapping-dir "d") " down")
  1644. X             (t ""))
  1645. X           (nth which msgs)
  1646. X           (if inv "Inv " "") (if hyp "Hyp " "")
  1647. X           (if prefix (concat (char-to-string prefix) "-") ""))
  1648. X      (setq key (read-char))
  1649. X      (cond ((= key ?\C-g)
  1650. X         (keyboard-quit))
  1651. X        ((= key ??)
  1652. X         (setq which (% (1+ which) (length msgs))))
  1653. X        ((= key ?I)
  1654. X         (setq inv (not inv)
  1655. X           prefix nil))
  1656. X        ((= key ?H)
  1657. X         (setq hyp (not hyp)
  1658. X           prefix nil))
  1659. X        ((eq key prefix)
  1660. X         (setq prefix nil))
  1661. X        ((and (memq key '(?b ?c ?k ?m)) (null prefix))
  1662. X         (setq inv nil hyp nil
  1663. X           prefix key))
  1664. X        ((eq prefix ?m)
  1665. X         (setq prefix nil)
  1666. X         (if (eq key ?e)
  1667. X         (setq calc-mapping-dir nil)
  1668. X           (if (memq key '(?r ?c ?a ?d))
  1669. X           (setq calc-mapping-dir (char-to-string key))
  1670. X         (beep))))
  1671. X        ((memq key '(?\$ ?\'))
  1672. X         (let ((expr (if (eq key ?\$)
  1673. X                 (progn
  1674. X                   (setq calc-dollar-used 1)
  1675. X                   (if calc-dollar-values
  1676. X                   (list (car calc-dollar-values))
  1677. X                 (error "Stack underflow")))
  1678. X               (calc-do-alg-entry "" "Function: ")))
  1679. X           (arglist nil))
  1680. X           (if (/= (length expr) 1)
  1681. X           (error "Bad format"))
  1682. X           (if (eq (car-safe (car expr)) 'calcFunc-lambda)
  1683. X           (setq oper (list "$" (- (length (car expr)) 2) (car expr))
  1684. X             done t)
  1685. X         (calc-default-formula-arglist (car expr))
  1686. X         (setq arglist (sort arglist 'string-lessp)
  1687. X               arglist (read-from-minibuffer
  1688. X                "Function argument list: "
  1689. X                (if arglist
  1690. X                    (prin1-to-string arglist)
  1691. X                  "()")
  1692. X                minibuffer-local-map
  1693. X                t))
  1694. X         (setq oper (list "$"
  1695. X                  (length arglist)
  1696. X                  (append '(calcFunc-lambda)
  1697. X                      (mapcar
  1698. X                       (function
  1699. X                        (lambda (x)
  1700. X                          (list 'var
  1701. X                            x
  1702. X                            (intern
  1703. X                             (concat
  1704. X                              "var-"
  1705. X                              (symbol-name x))))))
  1706. X                       arglist)
  1707. X                      expr))
  1708. X               done t))))
  1709. X        ((setq oper (assq key (cond ((eq prefix ?b) calc-b-oper-keys)
  1710. X                    ((eq prefix ?c) calc-c-oper-keys)
  1711. X                    ((eq prefix ?k) calc-k-oper-keys)
  1712. X                    (inv (if hyp
  1713. X                         calc-inv-hyp-oper-keys
  1714. X                           calc-inv-oper-keys))
  1715. X                    (t (if hyp
  1716. X                           calc-hyp-oper-keys
  1717. X                         calc-oper-keys)))))
  1718. X         (if (eq (nth 1 oper) 'user)
  1719. X         (let ((func (intern
  1720. X                  (completing-read "Function name: "
  1721. X                           obarray 'fboundp
  1722. X                           nil "calcFunc-"))))
  1723. X           (if nargs
  1724. X               (setq oper (list "z" nargs func)
  1725. X                 done t)
  1726. X             (if (and (fboundp func)
  1727. X                  (consp (symbol-function func)))
  1728. X             (let* ((defn (symbol-function func))
  1729. X                (args (nth 1 defn)))
  1730. X               (if (and (eq (car defn) 'lambda)
  1731. X                    args
  1732. X                    (not (memq (car args)
  1733. X                           '(&optional &rest)))
  1734. X                    (or (memq (nth 2 args)
  1735. X                          '(&optional &rest nil))
  1736. X                    (memq (nth 1 args)
  1737. X                          '(&optional &rest))))
  1738. X                   (setq oper (list "z"
  1739. X                        (if (memq (nth 1 args)
  1740. X                              '(&optional
  1741. X                                &rest nil))
  1742. X                            1 2)
  1743. X                        func)
  1744. X                     done t)
  1745. X                 (error "Function is not suitable for this operation")))
  1746. X               (message "Number of arguments: ")
  1747. X               (let ((nargs (read-char)))
  1748. X             (if (and (>= nargs ?0) (<= nargs ?9))
  1749. X                 (setq oper (list "z" (- nargs ?0) func)
  1750. X                   done t)
  1751. X               (beep))))))
  1752. X           (setq done t)))
  1753. X        (t (beep))))
  1754. X    (and nargs
  1755. X     (/= nargs (nth 1 oper))
  1756. X     (error "Must be a %d-argument operator" nargs))
  1757. X    (append (cdr oper)
  1758. X        (list
  1759. X         (concat (if prefix (char-to-string prefix) "")
  1760. X             (if inv "I" "") (if hyp "H" "")
  1761. X             (char-to-string key)))))
  1762. X)
  1763. X
  1764. X(defconst calc-oper-keys '( ( ?+ 2 calcFunc-add )
  1765. X                ( ?- 2 calcFunc-sub )
  1766. X                ( ?* 2 calcFunc-mul )
  1767. X                ( ?/ 2 calcFunc-div )
  1768. X                ( ?^ 2 calcFunc-pow )
  1769. X                ( ?| 2 calcFunc-vconcat )
  1770. X                ( ?% 2 calcFunc-mod )
  1771. X                ( ?\\ 2 calcFunc-idiv )
  1772. X                ( ?: 2 calcFunc-fdiv )
  1773. X                ( ?! 1 calcFunc-fact )
  1774. X                ( ?n 1 calcFunc-neg )
  1775. X                ( ?x user )
  1776. X                ( ?z user )
  1777. X                ( ?A 1 calcFunc-abs )
  1778. X                ( ?J 1 calcFunc-conj )
  1779. X                ( ?G 1 calcFunc-arg )
  1780. X                ( ?Q 1 calcFunc-sqrt )
  1781. X                ( ?N 2 calcFunc-min )
  1782. X                ( ?X 2 calcFunc-max )
  1783. X                ( ?F 1 calcFunc-floor )
  1784. X                ( ?R 1 calcFunc-round )
  1785. X                ( ?S 1 calcFunc-sin )
  1786. X                ( ?C 1 calcFunc-cos )
  1787. X                ( ?T 1 calcFunc-tan )
  1788. X                ( ?L 1 calcFunc-ln )
  1789. X                ( ?E 1 calcFunc-exp )
  1790. X                ( ?B 2 calcFunc-log )
  1791. X))
  1792. X(defconst calc-b-oper-keys '( ( ?a 2 calcFunc-and )
  1793. X                  ( ?o 2 calcFunc-or )
  1794. X                  ( ?x 2 calcFunc-xor )
  1795. X                  ( ?d 2 calcFunc-diff )
  1796. X                  ( ?n 1 calcFunc-not )
  1797. X                  ( ?c 1 calcFunc-clip )
  1798. X))
  1799. X(defconst calc-c-oper-keys '( ( ?d 1 calcFunc-deg )
  1800. X                  ( ?r 1 calcFunc-rad )
  1801. X                  ( ?h 1 calcFunc-hms )
  1802. X                  ( ?f 1 calcFunc-float )
  1803. X                  ( ?F 1 calcFunc-frac )
  1804. X))
  1805. X(defconst calc-k-oper-keys '( ( ?g 2 calcFunc-gcd )
  1806. X                  ( ?l 2 calcFunc-lcm )
  1807. X                  ( ?b 2 calcFunc-choose )
  1808. X                  ( ?d 1 calcFunc-dfact )
  1809. X                  ( ?m 1 calcFunc-moebius )
  1810. X                  ( ?p 2 calcFunc-perm )
  1811. X                  ( ?r 1 calcFunc-random )
  1812. X                  ( ?t 1 calcFunc-totient )
  1813. X))
  1814. X(defconst calc-inv-oper-keys '( ( ?F 1 calcFunc-ceil )
  1815. X                ( ?R 1 calcFunc-trunc )
  1816. X                ( ?Q 1 calcFunc-sqr )
  1817. X                ( ?S 1 calcFunc-arcsin )
  1818. X                ( ?C 1 calcFunc-arccos )
  1819. X                ( ?T 1 calcFunc-arctan )
  1820. X                ( ?L 1 calcFunc-exp )
  1821. X                ( ?E 1 calcFunc-ln )
  1822. X))
  1823. X(defconst calc-hyp-oper-keys '( ( ?F 1 calcFunc-ffloor )
  1824. X                ( ?R 1 calcFunc-fround )
  1825. X                ( ?S 1 calcFunc-sinh )
  1826. X                ( ?C 1 calcFunc-cosh )
  1827. X                ( ?T 1 calcFunc-tanh )
  1828. X                ( ?L 1 calcFunc-log10 )
  1829. X                ( ?E 1 calcFunc-exp10 )
  1830. X))
  1831. X(defconst calc-inv-hyp-oper-keys '( ( ?F 1 calcFunc-fceil )
  1832. X                    ( ?R 1 calcFunc-ftrunc )
  1833. X                    ( ?S 1 calcFunc-arcsinh )
  1834. X                    ( ?C 1 calcFunc-arccosh )
  1835. X                    ( ?T 1 calcFunc-arctanh )
  1836. X                    ( ?L 1 calcFunc-exp10 )
  1837. X                    ( ?E 1 calcFunc-log10 )
  1838. X))
  1839. X
  1840. X
  1841. X
  1842. X
  1843. X;;; User menu.
  1844. X
  1845. X(defun calc-user-key-map ()
  1846. X  (cdr (elt calc-mode-map ?z))
  1847. X)
  1848. X
  1849. X(defun calc-z-prefix-help ()
  1850. X  (interactive)
  1851. X  (let* ((msgs nil)
  1852. X     (buf "")
  1853. X     (kmap (sort (copy-sequence (calc-user-key-map))
  1854. X             (function (lambda (x y) (< (car x) (car y))))))
  1855. X     (flags (apply 'logior
  1856. X               (mapcar (function
  1857. X                (lambda (k)
  1858. X                  (calc-user-function-classify (car k))))
  1859. X                   kmap))))
  1860. X    (if (= (logand flags 8) 0)
  1861. X    (calc-user-function-list kmap 7)
  1862. X      (calc-user-function-list kmap 1)
  1863. SHAR_EOF
  1864. echo "End of part 5"
  1865. echo "File calc-ext.el is continued in part 6"
  1866. echo "6" > s2_seq_.tmp
  1867. exit 0
  1868.